Skip to content

check the layer media type before flashing#9

Open
bennyz wants to merge 3 commits intojumpstarter-dev:mainfrom
bennyz:fix-layer-selection
Open

check the layer media type before flashing#9
bennyz wants to merge 3 commits intojumpstarter-dev:mainfrom
bennyz:fix-layer-selection

Conversation

@bennyz
Copy link
Copy Markdown
Member

@bennyz bennyz commented Mar 18, 2026

To avoid flashing non disk layers we need to check the media type

@coderabbitai
Copy link
Copy Markdown

coderabbitai bot commented Mar 18, 2026

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

The changes enhance OCI manifest layer selection by introducing an optional artifact_type field to ImageManifest and refining the get_single_layer() method to support artifact-type-driven layer prioritization with improved media-type validation and error handling.

Changes

Cohort / File(s) Summary
Manifest Enhancement
src/fls/oci/manifest.rs
Added optional artifact_type field to ImageManifest. Modified get_single_layer() to return single-layer manifests directly, prioritize layers matching artifact_type for multi-layer manifests, fallback to application/vnd.automotive.disk prefix matching, and return error when no suitable disk layer exists. Added comprehensive unit tests.
Layer Validation
src/fls/oci/from_oci.rs
Added upfront validation requiring selected OCI layer media_type to start with application/vnd.automotive.disk, returning early error if validation fails.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Poem

🐰 Artifacts and layers dance in the manifest,
We hop through each disk type to find the best!
With artifact_type guiding our precise selection,
No more ambiguity—just validation perfection! 🎯
From single to many, your logic now springs,
A rabbit approves of these OCI-powered things! ✨

🚥 Pre-merge checks | ✅ 3
✅ Passed checks (3 passed)
Check name Status Explanation
Title check ✅ Passed The title accurately describes the main change: adding media type validation before flashing OCI layers to prevent non-disk artifacts.
Description check ✅ Passed The description is related to the changeset, explaining the purpose of checking media types to avoid flashing non-disk layers.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🧹 Nitpick comments (1)
src/fls/oci/manifest.rs (1)

67-69: Add direct tests for the new selection rules.

A couple of focused unit tests for (1) artifact_type selection, (2) single non-disk layer rejection, and (3) the no-match error would cover the new branches in get_single_layer(). The current tests in this file only exercise parsing.

Also applies to: 149-168

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/fls/oci/manifest.rs` around lines 67 - 69, Add three focused unit tests
for Manifest::get_single_layer covering the new selection branches: (1) create a
manifest with artifact_type set and layers such that the correct layer is chosen
then assert get_single_layer returns that layer, (2) create a manifest with a
single layer whose mediaType is not a disk type and assert get_single_layer
returns the expected rejection/error, and (3) create a manifest with no matching
layers and assert get_single_layer returns the no-match error. Locate the
Manifest struct and the get_single_layer method to construct test Manifests and
expected Layer descriptors, use the same error types returned by
get_single_layer for assertions, and add these tests adjacent to the existing
parsing tests so they exercise lines handling artifact_type and the
layer-selection branches.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@src/fls/oci/manifest.rs`:
- Around line 145-163: The early-return and artifact_type match currently accept
any layer regardless of media_type; update the selection logic in manifest.rs so
every successful path validates the layer.media_type against the allowed
flashable disk types (e.g., check starts_with("application/vnd.automotive.disk")
or an equivalent allowed list) before returning; specifically, when
m.layers.len() == 1 verify m.layers[0].media_type is flashable, when matching
via m.artifact_type ensure the found layer also has a flashable media_type, and
keep the existing fallback that finds the first layer whose media_type
starts_with the disk prefix.

---

Nitpick comments:
In `@src/fls/oci/manifest.rs`:
- Around line 67-69: Add three focused unit tests for Manifest::get_single_layer
covering the new selection branches: (1) create a manifest with artifact_type
set and layers such that the correct layer is chosen then assert
get_single_layer returns that layer, (2) create a manifest with a single layer
whose mediaType is not a disk type and assert get_single_layer returns the
expected rejection/error, and (3) create a manifest with no matching layers and
assert get_single_layer returns the no-match error. Locate the Manifest struct
and the get_single_layer method to construct test Manifests and expected Layer
descriptors, use the same error types returned by get_single_layer for
assertions, and add these tests adjacent to the existing parsing tests so they
exercise lines handling artifact_type and the layer-selection branches.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 55bbc641-f85a-4511-a0be-17bb83c99ad0

📥 Commits

Reviewing files that changed from the base of the PR and between 60e5a9b and eab5e55.

📒 Files selected for processing (1)
  • src/fls/oci/manifest.rs

Comment on lines +145 to +163
if m.layers.len() == 1 {
return Ok(&m.layers[0]);
}

// If artifactType is set, find the layer matching it
if let Some(ref artifact_type) = m.artifact_type {
if let Some(layer) = m.layers.iter().find(|l| l.media_type == *artifact_type) {
return Ok(layer);
}
}

// Fall back to the first disk image layer
if let Some(layer) = m
.layers
.iter()
.find(|l| l.media_type.starts_with("application/vnd.automotive.disk"))
{
return Ok(layer);
}
Copy link
Copy Markdown

@coderabbitai coderabbitai bot Mar 18, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Validate all successful paths against the flashable media types.

Line 145 returns the only layer before any media-type check, and Lines 149-153 will also accept any artifact_type match. That still lets a non-disk blob through this path, which is exactly what this PR is trying to prevent.

Minimal fix
             Manifest::Image(ref m) => {
+                let is_flashable = |layer: &Descriptor| {
+                    layer.media_type.starts_with("application/vnd.automotive.disk")
+                };
+
                 if m.layers.is_empty() {
                     return Err("Manifest has no layers".to_string());
                 }
 
                 if m.layers.len() == 1 {
-                    return Ok(&m.layers[0]);
+                    let layer = &m.layers[0];
+                    return if is_flashable(layer) {
+                        Ok(layer)
+                    } else {
+                        Err(format!("Layer media type '{}' is not flashable", layer.media_type))
+                    };
                 }
 
                 // If artifactType is set, find the layer matching it
                 if let Some(ref artifact_type) = m.artifact_type {
-                    if let Some(layer) = m.layers.iter().find(|l| l.media_type == *artifact_type) {
+                    if let Some(layer) = m.layers.iter().find(|l| {
+                        l.media_type == *artifact_type && is_flashable(l)
+                    }) {
                         return Ok(layer);
                     }
                 }
 
                 // Fall back to the first disk image layer
                 if let Some(layer) = m
                     .layers
                     .iter()
-                    .find(|l| l.media_type.starts_with("application/vnd.automotive.disk"))
+                    .find(|l| is_flashable(l))
                 {
                     return Ok(layer);
                 }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/fls/oci/manifest.rs` around lines 145 - 163, The early-return and
artifact_type match currently accept any layer regardless of media_type; update
the selection logic in manifest.rs so every successful path validates the
layer.media_type against the allowed flashable disk types (e.g., check
starts_with("application/vnd.automotive.disk") or an equivalent allowed list)
before returning; specifically, when m.layers.len() == 1 verify
m.layers[0].media_type is flashable, when matching via m.artifact_type ensure
the found layer also has a flashable media_type, and keep the existing fallback
that finds the first layer whose media_type starts_with the disk prefix.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

+1

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@mangelajo, thanks for the confirmation! The fix is straightforward — every successful return path in get_single_layer needs to validate the layer's media type against the flashable disk prefix. Here's the suggested update:

pub fn get_single_layer(&self) -> Result<&Descriptor, String> {
    match self {
        Manifest::Image(ref m) => {
            let is_flashable = |layer: &Descriptor| {
                layer.media_type.starts_with("application/vnd.automotive.disk")
            };

            if m.layers.is_empty() {
                return Err("Manifest has no layers".to_string());
            }

            if m.layers.len() == 1 {
                let layer = &m.layers[0];
                return if is_flashable(layer) {
                    Ok(layer)
                } else {
                    Err(format!(
                        "Layer media type '{}' is not a flashable disk image",
                        layer.media_type
                    ))
                };
            }

            // If artifactType is set, find a layer matching it that is also flashable
            if let Some(ref artifact_type) = m.artifact_type {
                if let Some(layer) = m.layers.iter().find(|l| {
                    l.media_type == *artifact_type && is_flashable(l)
                }) {
                    return Ok(layer);
                }
            }

            // Fall back to the first disk image layer
            if let Some(layer) = m.layers.iter().find(|l| is_flashable(l)) {
                return Ok(layer);
            }

            Err(format!(
                "No disk image layer found among {} layers",
                m.layers.len()
            ))
        }
        Manifest::Index(_) => Err(
            "Cannot get layer from manifest index - need to resolve platform first".to_string(),
        ),
    }
}

Key changes vs the current PR:

  • Single-layer path: now rejects the layer if its media_type doesn't start with application/vnd.automotive.disk.
  • artifact_type path: the closure additionally requires is_flashable, so a matching artifact type alone is not enough.
  • Fallback path: already correct, just uses the shared is_flashable closure for consistency.

Would you like me to open this as a plan for code changes?

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed in ab866a4. All three return paths in get_single_layer() now validate the media type using a shared is_flashable closure that checks for the application/vnd.automotive.disk prefix:

  1. Single layer path: now returns an error if the layer has a non-flashable media type
  2. artifact_type path: now requires both media_type == artifact_type AND is_flashable
  3. Fallback path: uses the same is_flashable closure (functionally unchanged, just refactored for consistency)

Also added unit tests covering: single flashable layer acceptance, single non-disk layer rejection, artifact_type-based selection, and no-match error.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed — but with an important design adjustment: get_single_layer() is shared between the flash and extract paths. The extraction path (extract_files_from_oci_image_to_dir) legitimately needs to work with non-disk media types (e.g. tar+gzip layers), so adding flashable validation inside get_single_layer() broke the 5 oci_extract integration tests.

The fix instead:

  • Keeps get_single_layer() generic — single-layer manifests return the layer directly (callers decide what's valid)
  • Adds flashable validation in flash_from_oci() — the flash-specific path now rejects layers that don't start with application/vnd.automotive.disk
  • Multi-layer selection still prefers artifact_type match, then falls back to the first disk image layer

Also fixed the &&layer clippy lint (needless borrow).

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Skipped: comment is from another GitHub bot.

@bennyz bennyz requested a review from mangelajo March 18, 2026 18:15
if let Some(layer) = m
.layers
.iter()
.find(|l| l.media_type.starts_with("application/vnd.automotive.disk"))
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would probably add some other more generic media types as well, so the oci artifacts could be reused in other areas. applcation/vnd.embedded.disk, or similar.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@coderabbitai can you open a follow-up issue for this?

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧩 Analysis chain

🏁 Script executed:

gh issue create \
  --repo jumpstarter-dev/fls \
  --title "Support more generic media types for disk image layer selection" \
  --body "## Follow-up: Support more generic media types for disk image layer selection

Currently, the fallback layer selection in \`get_single_layer()\` (in \`src/fls/oci/manifest.rs\`) only matches layers whose \`mediaType\` starts with \`application/vnd.automotive.disk\`.

To allow OCI artifacts to be reused in other areas (e.g. embedded systems beyond automotive), the selection logic should also consider more generic media types such as \`application/vnd.embedded.disk\` or similar conventions.

### Suggested improvement

Expand the media type matching in the fallback layer selection to include additional generic disk image media types, for example:
- \`application/vnd.embedded.disk\`
- Other relevant generic media types as appropriate

This would make \`fls\` more broadly applicable beyond automotive use cases.

---

Raised by `@mangelajo` in `#9`: https://github.com/jumpstarter-dev/fls/pull/9#discussion_r3043976233" \
  --assignee mangelajo

Length of output: 48


@mangelajo, I've opened a follow-up issue for this: #12 – Support more generic media types for disk image layer selection.

It covers expanding the fallback layer selection in get_single_layer() to support more generic media types (e.g., application/vnd.embedded.disk) beyond the current application/vnd.automotive.disk prefix, making fls more broadly applicable beyond automotive use cases.

@mangelajo
Copy link
Copy Markdown
Member

@ambient-code please handle existing comments.

Copy link
Copy Markdown

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick comments (1)
src/fls/oci/manifest.rs (1)

340-365: Make the artifact_type test prove artifact_type precedence.

As written, this still passes if the artifact_type branch is removed, because the fallback path also returns the same layer. Use two flashable layers with different media types so the test verifies the explicit artifactType match wins, and add a regression case for a non-flashable artifactType.

🧪 Suggested test shape
 fn test_artifact_type_selection() {
     let json = r#"{
         "schemaVersion": 2,
-        "artifactType": "application/vnd.automotive.disk.raw",
+        "artifactType": "application/vnd.automotive.disk.qcow2",
         "config": {
             "mediaType": "application/vnd.oci.image.config.v1+json",
             "digest": "sha256:config123",
             "size": 100
         },
         "layers": [
             {
-                "mediaType": "application/vnd.oci.image.layer.v1.tar+gzip",
-                "digest": "sha256:layer1",
+                "mediaType": "application/vnd.automotive.disk.raw",
+                "digest": "sha256:disk-raw",
                 "size": 1000
             },
             {
-                "mediaType": "application/vnd.automotive.disk.raw",
-                "digest": "sha256:disk1",
+                "mediaType": "application/vnd.automotive.disk.qcow2",
+                "digest": "sha256:disk-qcow2",
                 "size": 9999
             }
         ]
     }"#;
     let manifest = Manifest::parse(json.as_bytes(), None).unwrap();
     let layer = manifest.get_single_layer().unwrap();
-    assert_eq!(layer.digest, "sha256:disk1");
+    assert_eq!(layer.digest, "sha256:disk-qcow2");
 }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/fls/oci/manifest.rs` around lines 340 - 365, The test
test_artifact_type_selection currently doesn't prove artifactType precedence
because the fallback path selects the same layer; update the test to include two
flashable layers with distinct mediaTypes (e.g., one with
"application/vnd.automotive.disk.raw" and another with a different flashable
mediaType) and set artifactType in the manifest JSON to match only one of them
so Manifest::parse(... ) and manifest.get_single_layer() must pick the layer
whose mediaType equals artifactType; also add a regression case where
artifactType is a non-flashable mediaType to assert that the fallback selection
logic is used (or an error is returned) to ensure the artifact_type branch is
actually exercised.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In `@src/fls/oci/manifest.rs`:
- Around line 340-365: The test test_artifact_type_selection currently doesn't
prove artifactType precedence because the fallback path selects the same layer;
update the test to include two flashable layers with distinct mediaTypes (e.g.,
one with "application/vnd.automotive.disk.raw" and another with a different
flashable mediaType) and set artifactType in the manifest JSON to match only one
of them so Manifest::parse(... ) and manifest.get_single_layer() must pick the
layer whose mediaType equals artifactType; also add a regression case where
artifactType is a non-flashable mediaType to assert that the fallback selection
logic is used (or an error is returned) to ensure the artifact_type branch is
actually exercised.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: ef4d7957-3342-4ec6-ac48-75165781075e

📥 Commits

Reviewing files that changed from the base of the PR and between eab5e55 and ab866a4.

📒 Files selected for processing (1)
  • src/fls/oci/manifest.rs

@ambient-code ambient-code bot force-pushed the fix-layer-selection branch from ab866a4 to 5dfbeb5 Compare April 8, 2026 09:44
Copy link
Copy Markdown

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@src/fls/oci/manifest.rs`:
- Around line 142-168: Update the stale doc comment for the method that selects
a disk image layer (the code using m.layers, m.artifact_type and
layer.media_type) to describe the new multi-layer selection rules: if only one
layer exists return it; otherwise, if m.artifact_type is set, return the layer
whose media_type equals the artifact_type; otherwise, fall back to the first
layer whose media_type starts with "application/vnd.automotive.disk"; if none
match, return an error. Mention these exact selection steps and the possible
error outcome so the doc matches the implementation.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 1a6f08f4-40ad-415c-9efe-89d42e815fd5

📥 Commits

Reviewing files that changed from the base of the PR and between 5dfbeb5 and 3c0afcb.

⛔ Files ignored due to path filters (1)
  • Cargo.lock is excluded by !**/*.lock
📒 Files selected for processing (14)
  • Cargo.toml
  • src/fls/decompress.rs
  • src/fls/download_error.rs
  • src/fls/fastboot.rs
  • src/fls/from_url.rs
  • src/fls/mod.rs
  • src/fls/oci/from_oci.rs
  • src/fls/oci/manifest.rs
  • src/fls/oci/registry.rs
  • src/fls/options.rs
  • src/fls/stream_utils.rs
  • src/lib.rs
  • src/main.rs
  • tests/oci_extract.rs
✅ Files skipped from review due to trivial changes (3)
  • Cargo.toml
  • src/fls/mod.rs
  • src/lib.rs
🚧 Files skipped from review as they are similar to previous changes (1)
  • src/fls/oci/from_oci.rs
👮 Files not reviewed due to content moderation or server errors (8)
  • src/fls/decompress.rs
  • src/fls/fastboot.rs
  • src/main.rs
  • src/fls/options.rs
  • src/fls/oci/registry.rs
  • src/fls/from_url.rs
  • tests/oci_extract.rs
  • src/fls/download_error.rs

bennyz and others added 2 commits April 12, 2026 13:05
To avoid flashing non disk layers we need to check the media type

Signed-off-by: Benny Zlotnik <bzlotnik@redhat.com>
Assisted-by: claude-sonnet-4.6
Address review feedback: add flashable media type validation
(application/vnd.automotive.disk.*) in the flash_from_oci function,
which is the correct place for flash-specific checks. Keep
get_single_layer() generic since it is also used by the extraction
path where any media type is valid.

For multi-layer manifests, get_single_layer() prefers artifact_type
matches and falls back to the first disk image layer.

Add unit tests for: artifact_type selection, single layer (any type)
returned, single flashable layer acceptance, and no-match error.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@bennyz bennyz force-pushed the fix-layer-selection branch from 3c0afcb to d9de095 Compare April 12, 2026 10:05
Copy link
Copy Markdown

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

♻️ Duplicate comments (1)
src/fls/oci/manifest.rs (1)

136-138: ⚠️ Potential issue | 🟡 Minor

Update stale get_single_layer() doc contract.

Line 137 still says multiple layers are an error, but current logic returns an artifact_type match or first disk layer for multi-layer manifests. Please align the doc with actual selection behavior.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/fls/oci/manifest.rs` around lines 136 - 138, The doc for
get_single_layer() is stale: it claims multiple layers are an error, but the
implementation actually matches artifact_type or selects the first disk layer
for multi-layer manifests; update the function comment above pub fn
get_single_layer(&self) -> Result<&Descriptor, String> to reflect the real
contract (describe that it returns the matched artifact_type layer when present,
otherwise the first disk layer, and only errors when no layers exist or no
suitable layer can be found), so the documentation matches the behavior of
get_single_layer.
🧹 Nitpick comments (1)
src/fls/oci/manifest.rs (1)

157-160: Extract disk media prefix to a shared constant.

The automotive disk prefix is hard-coded here and also used in flash-path validation (src/fls/oci/from_oci.rs:1815-1825). A shared constant would reduce drift risk.

Proposed refactor
 pub mod media_types {
@@
     pub const DOCKER_LAYER: &str = "application/vnd.docker.image.rootfs.diff.tar.gzip";
+    pub const AUTOMOTIVE_DISK_PREFIX: &str = "application/vnd.automotive.disk";
 }
@@
-                    .find(|l| l.media_type.starts_with("application/vnd.automotive.disk"))
+                    .find(|l| l.media_type.starts_with(media_types::AUTOMOTIVE_DISK_PREFIX))
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/fls/oci/manifest.rs` around lines 157 - 160, Extract the hard-coded
automotive disk media prefix ("application/vnd.automotive.disk" currently used
in manifest scanning and in flash-path validation) into a single shared constant
and replace the literal occurrences. Define a public constant (e.g.,
AUTOMOTIVE_DISK_MEDIA_PREFIX) in a common module or at the top of
src/fls/oci/manifest.rs (or a central constants module used by
src/fls/oci/from_oci.rs), then update the .media_type.starts_with check in the
code that iterates m.layers and the corresponding validation in from_oci.rs to
use that constant instead of the string literal.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Duplicate comments:
In `@src/fls/oci/manifest.rs`:
- Around line 136-138: The doc for get_single_layer() is stale: it claims
multiple layers are an error, but the implementation actually matches
artifact_type or selects the first disk layer for multi-layer manifests; update
the function comment above pub fn get_single_layer(&self) -> Result<&Descriptor,
String> to reflect the real contract (describe that it returns the matched
artifact_type layer when present, otherwise the first disk layer, and only
errors when no layers exist or no suitable layer can be found), so the
documentation matches the behavior of get_single_layer.

---

Nitpick comments:
In `@src/fls/oci/manifest.rs`:
- Around line 157-160: Extract the hard-coded automotive disk media prefix
("application/vnd.automotive.disk" currently used in manifest scanning and in
flash-path validation) into a single shared constant and replace the literal
occurrences. Define a public constant (e.g., AUTOMOTIVE_DISK_MEDIA_PREFIX) in a
common module or at the top of src/fls/oci/manifest.rs (or a central constants
module used by src/fls/oci/from_oci.rs), then update the .media_type.starts_with
check in the code that iterates m.layers and the corresponding validation in
from_oci.rs to use that constant instead of the string literal.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: d2f99286-340e-4131-a0c6-dc21f5e97890

📥 Commits

Reviewing files that changed from the base of the PR and between 3c0afcb and d9de095.

📒 Files selected for processing (2)
  • src/fls/oci/from_oci.rs
  • src/fls/oci/manifest.rs
✅ Files skipped from review due to trivial changes (1)
  • src/fls/oci/from_oci.rs

Use two distinct flashable layers so artifactType selection is
distinguishable from the fallback path. Add a regression test for
when artifactType matches no layer to verify fallback to disk media
type.

Signed-off-by: Benny Zlotnik <bzlotnik@redhat.com>
Assisted-by: claude-sonnet-4.6
@bennyz bennyz force-pushed the fix-layer-selection branch from d9de095 to e3f85ba Compare April 12, 2026 10:11
@bennyz bennyz requested a review from mangelajo April 12, 2026 13:24
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants